package me.firstapp.config;

import java.io.IOException;
import java.util.Properties;

import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import me.firstapp.bts.JobTask;
import me.firstapp.spi.bbs.CollectionService;
import me.firstapp.spi.bbs.ReplyService;
import me.firstapp.spi.bbs.SearchService;
import me.firstapp.spi.bbs.SectionService;
import me.firstapp.spi.bbs.TopicService;
import me.firstapp.spi.shop.OrderService;
import me.firstapp.spi.shop.ProductService;
import me.firstapp.spi.system.ApiClientService;
import me.firstapp.spi.system.StatisticsService;

@Configuration
@ComponentScan(basePackages = { "me.firstapp.bts" })
public class RootConfig {

	@Bean
	public PropertiesFactoryBean configProperties() {
		PropertiesFactoryBean configProperties = new PropertiesFactoryBean();
		configProperties.setLocations(new ClassPathResource("config.properties"));
		return configProperties;
	}

	// ==============================缓存配置start========================================
	@Bean
	public RedisConnectionFactory redisCF(PropertiesFactoryBean configProperties) {
		JedisConnectionFactory cf = new JedisConnectionFactory();
		try {
			Properties properties = configProperties.getObject();
			cf.setHostName(properties.getProperty("redis.host"));
			cf.setPort(Integer.valueOf(properties.getProperty("redis.port", "6379")));
			cf.setPassword(properties.getProperty("redis.password"));
		} catch (IOException e) {
			e.printStackTrace();
		}

		return cf;
	}

	@Bean
	public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisCF) {
		RedisTemplate<String, Object> redis = new RedisTemplate<>();
		redis.setConnectionFactory(redisCF);
		return redis;
	}

	@Bean
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisCF) {
		return new StringRedisTemplate(redisCF);
	}
	// ==============================缓存配置end========================================

	// ==============================远程服务配置start========================================
	@Bean
	public HttpInvokerProxyFactoryBean sectionService(PropertiesFactoryBean configProperties) {
		HttpInvokerProxyFactoryBean proxy = new HttpInvokerProxyFactoryBean();
		try {
			Properties properties = configProperties.getObject();
			proxy.setServiceUrl(properties.getProperty("spi.server.url") + "/section.service");
			proxy.setServiceInterface(SectionService.class);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return proxy;
	}

	@Bean
	public HttpInvokerProxyFactoryBean topicService(PropertiesFactoryBean configProperties) {
		HttpInvokerProxyFactoryBean proxy = new HttpInvokerProxyFactoryBean();
		try {
			Properties properties = configProperties.getObject();
			proxy.setServiceUrl(properties.getProperty("spi.server.url") + "/topic.service");
			proxy.setServiceInterface(TopicService.class);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return proxy;
	}

	@Bean
	public HttpInvokerProxyFactoryBean replyService(PropertiesFactoryBean configProperties) {
		HttpInvokerProxyFactoryBean proxy = new HttpInvokerProxyFactoryBean();
		try {
			Properties properties = configProperties.getObject();
			proxy.setServiceUrl(properties.getProperty("spi.server.url") + "/reply.service");
			proxy.setServiceInterface(ReplyService.class);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return proxy;
	}

	@Bean
	public HttpInvokerProxyFactoryBean collectionService(PropertiesFactoryBean configProperties) {
		HttpInvokerProxyFactoryBean proxy = new HttpInvokerProxyFactoryBean();
		try {
			Properties properties = configProperties.getObject();
			proxy.setServiceUrl(properties.getProperty("spi.server.url") + "/collection.service");
			proxy.setServiceInterface(CollectionService.class);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return proxy;
	}

	@Bean
	public HttpInvokerProxyFactoryBean orderService(PropertiesFactoryBean configProperties) {
		HttpInvokerProxyFactoryBean proxy = new HttpInvokerProxyFactoryBean();
		try {
			Properties properties = configProperties.getObject();
			proxy.setServiceUrl(properties.getProperty("spi.server.url") + "/order.service");
			proxy.setServiceInterface(OrderService.class);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return proxy;
	}

	@Bean
	public HttpInvokerProxyFactoryBean searchService(PropertiesFactoryBean configProperties) {
		HttpInvokerProxyFactoryBean proxy = new HttpInvokerProxyFactoryBean();
		try {
			Properties properties = configProperties.getObject();
			proxy.setServiceUrl(properties.getProperty("spi.server.url") + "/search.service");
			proxy.setServiceInterface(SearchService.class);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return proxy;
	}

	@Bean
	public HttpInvokerProxyFactoryBean productService(PropertiesFactoryBean configProperties) {
		HttpInvokerProxyFactoryBean proxy = new HttpInvokerProxyFactoryBean();
		try {
			Properties properties = configProperties.getObject();
			proxy.setServiceUrl(properties.getProperty("spi.server.url") + "/product.service");
			proxy.setServiceInterface(ProductService.class);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return proxy;
	}

	@Bean
	public HttpInvokerProxyFactoryBean apiClientService(PropertiesFactoryBean configProperties) {
		HttpInvokerProxyFactoryBean proxy = new HttpInvokerProxyFactoryBean();
		try {
			Properties properties = configProperties.getObject();
			proxy.setServiceUrl(properties.getProperty("spi.server.url") + "/apiClient.service");
			proxy.setServiceInterface(ApiClientService.class);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return proxy;
	}

	@Bean
	public HttpInvokerProxyFactoryBean statisticsService(PropertiesFactoryBean configProperties) {
		HttpInvokerProxyFactoryBean proxy = new HttpInvokerProxyFactoryBean();
		try {
			Properties properties = configProperties.getObject();
			proxy.setServiceUrl(properties.getProperty("spi.server.url") + "/statistics.service");
			proxy.setServiceInterface(StatisticsService.class);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return proxy;
	}

	// ==============================远程服务配置end========================================

	// ==============================定時任務配置start========================================
	@Bean
	public SchedulerFactoryBean schedulerFactory(JobTask jobTask) {
		SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
		scheduler.setAutoStartup(true);
		CronTriggerFactoryBean topicTrigger = topicTrigger(jobTask);
		CronTriggerFactoryBean cancelOrderTrigger = cancelOrderTrigger(jobTask);
		CronTriggerFactoryBean sectionTrigger = sectionTrigger(jobTask);
		// CronTriggerFactoryBean updateSearchDataTrigger =
		// updateSearchDataTrigger(jobTask);
		CronTriggerFactoryBean updateApiClientTrigger = updateApiClientTrigger(jobTask);
		CronTriggerFactoryBean statisticsTrigger = statisticsTrigger(jobTask);
		scheduler.setTriggers(topicTrigger.getObject(), cancelOrderTrigger.getObject(), sectionTrigger.getObject(),
				updateApiClientTrigger.getObject(), statisticsTrigger.getObject());
		return scheduler;
	}

	@Bean
	public JobTask jobTask() {
		return new JobTask();
	}

	// ==============================話題相關定时任务start========================================
	@Bean(name = "topicJobDetail")
	public MethodInvokingJobDetailFactoryBean topicJobDetail(JobTask jobTask) {
		MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
		jobDetail.setTargetObject(jobTask);
		jobDetail.setTargetMethod("doTopicTask");
		jobDetail.setConcurrent(false);
		return jobDetail;
	}

	@Bean
	public CronTriggerFactoryBean topicTrigger(JobTask jobTask) {
		CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
		MethodInvokingJobDetailFactoryBean topicJobDetail = topicJobDetail(jobTask);
		trigger.setJobDetail(topicJobDetail.getObject());
		trigger.setCronExpression("0 0 0/3 * * ? *");// 百度搜索 quartz cron表达式
														// 在线生成器
		return trigger;
	}
	// ==============================話題相關定时任务end========================================

	// ==============================板块定时任务start========================================
	@Bean(name = "sectionJobDetail")
	public MethodInvokingJobDetailFactoryBean sectionJobDetail(JobTask jobTask) {
		MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
		jobDetail.setTargetObject(jobTask);
		jobDetail.setTargetMethod("doSectionTask");
		jobDetail.setConcurrent(false);
		return jobDetail;
	}

	@Bean
	public CronTriggerFactoryBean sectionTrigger(JobTask jobTask) {
		CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
		MethodInvokingJobDetailFactoryBean sectionDetail = sectionJobDetail(jobTask);
		trigger.setJobDetail(sectionDetail.getObject());
		trigger.setCronExpression("0 0 0/3 * * ? *");// 百度搜索 quartz cron表达式
														// 在线生成器
		return trigger;
	}
	// ==============================板块定时任务end========================================

	// ==============================订单取消定时任务start=========================================
	@Bean(name = "cancelOrderJobDetail")
	public MethodInvokingJobDetailFactoryBean cancelOrderJobDetail(JobTask jobTask) {
		MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
		jobDetail.setTargetObject(jobTask);
		jobDetail.setTargetMethod("doCancelOutTimeOrderTask");
		jobDetail.setConcurrent(true);
		return jobDetail;
	}

	@Bean
	public CronTriggerFactoryBean cancelOrderTrigger(JobTask jobTask) {
		CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
		MethodInvokingJobDetailFactoryBean cancelOrderJobDetail = cancelOrderJobDetail(jobTask);
		trigger.setJobDetail(cancelOrderJobDetail.getObject());
		trigger.setCronExpression("0 0 0/2 * * ? *");// 从 0 分钟开始,每 2小时执行一次
		return trigger;
	}
	// ==============================订单取消定定时任务end========================================

	// ==============================更新话题搜索数据定时任务start=========================================
	// @Bean(name = "updateSearchDataJobDetail")
	// public MethodInvokingJobDetailFactoryBean
	// updateSearchDataJobDetail(JobTask jobTask) {
	// MethodInvokingJobDetailFactoryBean jobDetail = new
	// MethodInvokingJobDetailFactoryBean();
	// jobDetail.setTargetObject(jobTask);
	// jobDetail.setTargetMethod("doUpdateSearchDataTask");
	// jobDetail.setConcurrent(true);
	// return jobDetail;
	// }
	//
	// @Bean
	// public CronTriggerFactoryBean updateSearchDataTrigger(JobTask jobTask) {
	// CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
	// MethodInvokingJobDetailFactoryBean updateSearchDataJobDetail =
	// updateSearchDataJobDetail(jobTask);
	// trigger.setJobDetail(updateSearchDataJobDetail.getObject());
	// trigger.setCronExpression("0 0 0 1/1 * ? *");// 每天执行一次
	// return trigger;
	// }
	// ==============================更新话题搜索数据定时任务end========================================

	// ==============================更新ApiClient定时任务start=========================================
	@Bean(name = "updateApiClientJobDetail")
	public MethodInvokingJobDetailFactoryBean updateApiClientJobDetail(JobTask jobTask) {
		MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
		jobDetail.setTargetObject(jobTask);
		jobDetail.setTargetMethod("doUpdateApiClientTask");
		jobDetail.setConcurrent(true);
		return jobDetail;
	}

	@Bean
	public CronTriggerFactoryBean updateApiClientTrigger(JobTask jobTask) {
		CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
		MethodInvokingJobDetailFactoryBean updateApiClientJobDetail = updateApiClientJobDetail(jobTask);
		trigger.setJobDetail(updateApiClientJobDetail.getObject());
		trigger.setCronExpression("0 0 0 1/1 * ? *");// 每天执行一次
		// trigger.setCronExpression("0 0/5 * * * ? ");
		return trigger;
	}
	// ==============================更新ApiClient定时任务end=========================================

	@Bean(name = "statisticsJobDetail")
	public MethodInvokingJobDetailFactoryBean statisticsJobDetail(JobTask jobTask) {
		MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
		jobDetail.setTargetObject(jobTask);
		jobDetail.setTargetMethod("doStatisticsTask");
		jobDetail.setConcurrent(true);
		return jobDetail;
	}

	@Bean
	public CronTriggerFactoryBean statisticsTrigger(JobTask jobTask) {
		CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
		MethodInvokingJobDetailFactoryBean statisticsJobDetail = statisticsJobDetail(jobTask);
		trigger.setJobDetail(statisticsJobDetail.getObject());
		// trigger.setCronExpression("0 0 0 1/1 * ? *");// 每天执行一次
		trigger.setCronExpression("0 0/30 * * * ? ");
		return trigger;
	}

	// ==============================定時任務配置end=====================================================
}
